package com.bpmn.flow.service.impl;

import com.bpmn.common.exception.ServiceException;
import com.bpmn.common.holder.TenantContextHolder;
import com.bpmn.flow.dto.ProcessStartDTO;
import com.bpmn.flow.service.ProcessStartService;
import com.bpmn.utils.QueryUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author rain
 * @date 2025年01月06日 10:35
 */
@Service
@Slf4j
public class ProcessStartServiceImpl implements ProcessStartService {

    @Resource
    private RuntimeService runtimeService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String startProcess(ProcessStartDTO dto) {
        // 获取当前用户
        String userId = dto.getUserId();
        String tenantId = TenantContextHolder.getTenantId();
        // 查询流程定义
        ProcessDefinition definition = QueryUtils.definitionQuery().processDefinitionKey(dto.getProcessKey()).active().singleResult();
        if (definition == null || definition.isSuspended()) {
            throw new ServiceException("流程定义不存在或未激活");
        }
        try {
            // 启动流程实例
            ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
                    .processDefinitionId(definition.getId())
                    .tenantId(tenantId)
                    .businessKey(dto.getBusinessKey())
                    // 将流程定义名称 作为 流程实例名称
                    .name(definition.getName().trim())
                    // 添加自定义变量
                    .variables(dto.getVariables())
                    .start();
            // 记录操作日志
            log.info("Process[{}] started by user[{}]", definition.getId(), userId);
            return processInstance.getId();
        } catch (Exception e) {
            log.error("Start process failed", e);
            throw new ServiceException("启动流程失败: " + e.getMessage());
        }
    }
}
